import re

from django_redis import get_redis_connection
from rest_framework import serializers
from rest_framework_jwt.settings import api_settings

from answers.models import Answers
from answers.serializers import AnswerSerializer
from educations.serializers import EducationSerializer
from experience.serializers import ExperienceSerializer
from mlh.utils.fastdfs.fdfs_storage import FastDFSStorage
from questions.serializers import QuestionsSerializer
from share.serializers import ShareSerializer
from users.constants import TEST
from users.models import User


class UserSerializer(serializers.ModelSerializer):
    sms_code = serializers.CharField(label="短信验证码", write_only=True)
    allow = serializers.CharField(label="同意协议", write_only=True)
    # 上面的字段只有写入的时候，才会起作用.
    token = serializers.CharField(label="JWT_token", read_only=True)

    class Meta:
        model = User
        fields = ("id", "nickname", "mobile", "password", "allow", "sms_code", "token")
        extra_kwargs = {
            "nickname": {
                "min_length": 2,
                "max_length": 10,
                "error_messages": {
                    "min_length": "仅允许2-10个的昵称或名字",
                    "max_length": "仅允许2-10个的昵称或名字"
                }
            },
            # 由于字段默认都是双向性的，所以需要更改属性
            "password": {
                "write_only": True,
                "min_length": 6,
                "max_length": 20,
                "error_messages": {
                    "min_length": "仅允许6-20个的昵称或名字",
                    "max_length": "仅允许6-20个的昵称或名字"
                }

            }
        }

    def validated_mobile(self, value):
        # 专门验证某一字段,传进来就是该字段的值
        if not re.match(r"^1[3-9]\d{9}$", value):
            raise serializers.ValidationError("手机号格式错误")
        return value

    def validate_allow(self, value):
        # 检测用户是否勾选协议
        if value != "true":
            raise serializers.ValidationError("请同意用户协议")
        return value

    def validate(self, data):
        redis_conn = get_redis_connection("verify_codes")
        mobile = data["mobile"]
        real_sms_code = redis_conn.get("sms_%s" % mobile)
        print(real_sms_code)
        if real_sms_code is None:
            raise serializers.ValidationError("验证码过期")
        if data["sms_code"] != real_sms_code.decode():
            raise serializers.ValidationError("短信验证码输入错误")
        return data

    def create(self, validated_data):
        # 由于用户的密码需要加密，所以重写序列化器提供的创建方法
        # print(validated_data)
        del validated_data["sms_code"]
        del validated_data["allow"]
        # 　删除不需要写入数据库的中的
        # user = super().create(validated_data)  # 调用父类方法，得到对象
        # print(validated_data)
        nickname = validated_data["nickname"]
        mobile = validated_data["mobile"]
        print(mobile, nickname)
        user = User.objects.create(nickname=nickname, mobile=mobile, username=mobile)
        # user = User.objects.create(**validated_data)
        user.set_password(validated_data["password"])
        user.save()

        # # 手动签发jwt token，由于是在序列化器中完成验证和保存的，所以在保存到数据库后，需要签发token.
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)  # 操作新建的对象
        token = jwt_encode_handler(payload)
        # 动态添加属性（由于user对象是根据模型类创建的对象，并没有token这个属性，利用对象的特性，在模型对象保存到数据库中，可以动态的给该对象设置一个属性，用于序列化时，发送到前段）
        user.token = token
        return user


class UserInfoSerializer(serializers.ModelSerializer):
    experiences = ExperienceSerializer(many=True)
    educations = EducationSerializer(many=True)  # 一查多时，可使用嵌套序列化
    questioner = QuestionsSerializer(many=True)
    answer = AnswerSerializer(many=True, read_only=True)

    class Meta:
        model = User
        fields = "__all__"

    extra_kwargs = {
        "skills": {
            "required": False

        },
        "password": {
            "write_only": True,
            "min_length": 6,
            "max_length": 20,
            "error_messages": {
                "min_length": "仅允许6-20个的密码",
                "max_length": "仅允许6-20个的密码"
            }
        },
        "real_name": {
            "min_length": 2,
            "max_length": 16,
            "error_messages": {
                "min_length": "仅允许2-16个的昵称或名字",
                "max_length": "仅允许2-16个的昵称或名字"
            }
        },
        "experiences": {
            "reuqired": False,

            "read_only": True
        },
        "educations": {
            "reuqired": False,
            "read_only": True
        },
        "questions": {
            "reuqired": False,
            "read_only": True
        }
    }

    def validate(self, attrs):
        print(attrs)

        if attrs.get("skills"):
            attrs1 = attrs.get("skills")
            ret = re.split(r"[;, ]", attrs1)
            # 循环遍历切片的列表，剔除空格
            labels = []
            for skill in ret:
                if skill != " " and skill not in labels:
                    labels.append(skill)

            # 判断用户输入的数据，若是不存在就保错
            for label in labels:
                if label not in TEST:
                    raise serializers.ValidationError("请按照下面的格式和技能表输入")
            labels = ",".join(labels)
            attrs["rskill"] = labels
            return attrs
        return attrs

    def validate_mobile(self, value):
        # 用专门验证手机视图去验证是否唯一，这里值验证格式
        # 邮箱会自己验证格式，因为继承的是django模型类提供的
        if not re.match(r"^1[3-9]\d{9}$", value):
            raise serializers.ValidationError("手机号格式错误")

        return value

    def validate_real_name(self, value):
        print(value)
        if len(value) < 2 or len(value) > 16:
            raise serializers.ValidationError("名字错误")
        return value

    def update(self, instance, validated_data):
        user = self.context["request"].user

        if validated_data.get("real_avatar"):
            value = validated_data.get("real_avatar")
            client = FastDFSStorage()
            file_name = client._save(name=None, content=value)
            r_filename = client.url(file_name)
            print(r_filename)
            user.avatar = r_filename
            user.save()
            return user

        if validated_data.get("password"):
            password = validated_data["password"]

            user.set_password(password)
            user.save()
            return user
        if validated_data.get("rskill"):
            labels = validated_data.get("rskill")
            user = self.context["request"].user
            user.skills = labels
            user.save()
            return user
        if validated_data.get("weixin") and validated_data.get("allow1"):
            weixin = validated_data.get("weixin")
            allow1 = validated_data.get("allow1")
            user = self.context["request"].user
            user.weixin = weixin
            user.allow1 = allow1
            user.save()
            return user

        return super().update(instance, validated_data)


# class UserQuestionsViewSerializer(serializers.ModelSerializer):
#     class Meta:
#         model = Answers
#
#
# class UserQuestionSerializer(serializers.Serializer):
#     questions = QuestionsSerializer()
#
#     fields = ("questions",)


class UserAnswerSerializer(serializers.ModelSerializer):
    answer = AnswerSerializer(many=True, read_only=True)

    class Meta:
        model = User
        fields = "__all__"


class UserShareSerializer(serializers.ModelSerializer):
    users = ShareSerializer(many=True, read_only=True)

    class Meta:
        model = User
        fields = "__all__"
